const fs = require('fs');
const path = require('path');

/**
 * 转换本机路径为Unix风格路径。
 */
function escapePath (url) {
    if (!url) {
        console.error('路径为空');
        return ".";
    } else {
        return path.normalize(url);
    }
}

/**
 * 复制文件
 *
 * @param sourcePath
 * @param targetPath
 */
function copy(sourcePath, targetPath) {
    if (isFile(sourcePath)) {
        copyFile(sourcePath, targetPath);
    } else {
        copyDir(sourcePath, targetPath);
    }
}

function copyDir(sourcePath, targetPath) {
    var files = [];
    travelFileList(sourcePath, files);
    var len = files.length;
    for (var i = 0; i < len; i++) {
        files[i] = files[i].replace(path.normalize(sourcePath), "");
        let targetFile = path.join(targetPath, files[i]);
        createDir(targetFile);
        var pathA = path.join(sourcePath,  files[i]);
        var pathB = targetFile;
        copyFile(pathA, pathB);
    }
    return len >= 0;
}

/**
 * 是否是目录
 * @param dir
 * @returns {*}
 */
function isDirectory(dir) {
    dir = escapePath(dir);
    try {
        var stat = fs.statSync(dir);
    } catch (e) {
        return false;
    }
    return stat.isDirectory();
}

/**
 * 是否是文件
 * @param file
 * @returns {*}
 */
function isFile(file) {
    file = escapePath(file);
    try {
        var stat = fs.statSync(file);
    } catch (e) {
        return false;
    }
    return stat.isFile();
}

/**
 * 是否存在文件或文件夹
 * @param file
 * @returns {*}
 */
function exist(file) {
    if (file) {
        return fs.existsSync(file);
    }
    return false;
}

/**
 * 移除目录
 * @param file
 */
function removeDir(dir) {
    if (fs.existsSync(dir)) {
        let fileList = [];
        travelFileList(dir, fileList);
        let len = fileList.length;
        for (let i = 0; i < len; i++) {
            fs.unlinkSync(fileList[i]);
        }
        let dirList = [];
        travelDirList(dir, dirList);
        for (let i = dirList.length - 1; i >= 0; i--) {
            try {
                fs.rmdirSync(dirList[i]);
            } catch (e) {
                console.log("删除失败", dirList[i]);
            }
        }
    }
}

function removeFile(file) {
    if (isFile(file)) {
        fs.unlinkSync(file);
    }
}

function remove(file) {
    if (exist(file)) {
        if (isFile(file)) {
            removeFile(file);
        } else {
            removeDir(file);
        }
    }
}

function travel(dir, out) {
    var stats = fs.statSync(dir);
    if (stats) {
        if (stats.isDirectory()) {
            fs.readdirSync(dir).forEach(function (file) {
                let newDir = path.join(dir, file);
                travelFileList(newDir, out);
            });
        } else if (stats.isFile()) {
            out.push(dir);
        }
    }
}

// 遍历目录中的文件
function travelFileList(dir, out) {
    var stats = fs.statSync(dir);
    if (stats) {
        if (stats.isDirectory()) {
            fs.readdirSync(dir).forEach(function (file) {
                let newDir = path.join(dir, file);
                travelFileList(newDir, out);
            });
        } else if (stats.isFile()) {
            out.push(dir);
        }
    }
}

// 遍历文件夹
function travelDirList(dir, out) {
    var stats = fs.statSync(dir);
    if (stats.isDirectory()) {
        if (out.indexOf(dir) < 0) {
            out.push(dir);
        }
        fs.readdirSync(dir).forEach(function (file) {
            let newDir = path.join(dir, file);
            travelDirList(newDir, out);
        });
    }
}

/**
 * 重量命名文件或文件夹
 *
 * @param oldPath
 * @param newPath
 */
function rename(oldPath, newPath) {
    if (!exist(oldPath)) {
        console.error(`重命名错误,不存在文件${oldPath}`);
    } else {
        fs.renameSync(oldPath, newPath);
    }
}

// 创建子目标文件夹
function createDir(p) {
    p = escapePath(p);
    let needCreateDir = [];
    let curPath = isDirectory(p) || path.dirname(p);
    while (!exist(curPath)) {
        needCreateDir.unshift(curPath);
        curPath = path.dirname(curPath);
    }
    for (let i = 0; i < needCreateDir.length; i++) {
        fs.mkdirSync(needCreateDir[i]);
    }
}

function writeJSON(file, data) {
    file = escapePath(file);
    fs.writeFileSync(file, JSON.stringify(data), {encoding:"utf8"});
}

function readJSON(file) {
    let result = null;
    if (exist(file)) {
        try {
            let content = fs.readFileSync(file, "utf8");
            result = JSON.parse(content);
        } catch (e) {
            result = null;
        }
    } else {
        console.error(`文件${file}不存在`);
    }
    return result;
}

function readString(file) {
    let result = "";
    if (exist(file)) {
        let content = fs.readFileSync(file, {encoding:"utf8"});
        result = content;
    } else {
        console.error("文件不存在");
    }
    return result;
}

function writeString(filename, data) {
    fs.writeFileSync(filename, data, {encoding:"utf8"});
}

function readBytes(file) {
    let result = null;
    if (exist(file)) {
        let content = fs.readFileSync(file);
        result = content;
    } else {
        console.error(`文件${file}不存在`);
    }
    return result;
}

/**
 * 复制文件
 *
 * @param src   要被拷贝的源文件名称
 * @param dest  拷贝操作的目标文件名
 */
function copyFile(src, dest) {
    fs.copyFileSync(src, dest);
}

function removePromiseify(file) {
    return new Promise(function (resolve, reject) {
        if (!exist(file)) {
            console.log(`删除文件${file}成功`);
            resolve();
        } else {
            remove(file);
            if (!exist(file)) {
                resolve();
            } else {
                let count = 0;
                let time = setInterval(()=>{
                    if (!exist(file)) {
                        clearInterval(time);
                        console.log(`删除文件${file}成功`);
                        resolve();
                    } else {
                        count++;
                        if (count > 3) {
                            clearInterval(time);
                            reject(`删除文件${file}出错`);
                        }
                    }
                }, 3000);
            }
        }
    });
}

exports.remove = remove;
exports.copy = copy;
exports.removePromiseify = removePromiseify;
exports.isFile = isFile;
exports.exist = exist;
exports.readJSON = readJSON;
exports.writeJSON = writeJSON;
exports.readString = readString;
exports.writeString = writeString;
exports.readBytes = readBytes;
exports.rename = rename;
exports.travel = travel;
exports.createDir = createDir;
exports.travelFileList = travelFileList;
exports.travelDirList = travelDirList;
